Mehrere Schüsse

← Zurück zum Forum

Folgendes Problem möchte ich hier mal diskutieren, da ich zwar eine Lösung für mich gefunden habe, die aber recht umständlich und aufwendig und nicht ganz fehlerfrei erscheint:

In Assembler möchte ich einen Player mehrere Schüsse feuern lassen. Also maximal 4 zum Beispiel. Nun fragt man also den Strig0 ab und wenn der gedrückt wurde geht Schuss1 los. Beim nächsten drücken dann Schuss2 usw. Die laufenden Schüsse sind so lange blockiert, bis sie auf ein Hindernis gestossen sind und eine Aktion auslösen oder hinten aus dem Bildrand rausgelaufen sind und dann wieder für einen neuen Schuss zur Verfügung stehen. So simpel sich das anhört, so kompliziert finde ich die Umsetzung.

Ähnlich wie be den Zufallszahlen könnte ich mir hier etliche sehr gute Ansätze vorstellen... bin gespannt auf Eure Ideen. Gruß Peter

AntwortZitat

Hallo Peter,

ich habe keinen Programmcode, nur Ideen: es gibt die Möglichkeit, das Schüsse nur eine bestimmte Reichweite haben und "verschwinden" und wieder zur Verfügung stehen. Man muss nicht warten, bis die Schüsse den Bildschirmrand erreichen.

Das Hauptprogramm fragt STRIG(0) ab, setzt den Start-Wert (x/y/count) in Variablen/Speicherstellen.

Im VBI werden X oder/und Y angepasst und "count" heruntergezählt. Wenn "count" == 0, wird der Schuss "ausgeschaltet" und steht wieder zur Verfügung. Kollisions-Abfrage kann im VBI oder im Hauptprogramm geschehen, das Hauptprogramm muss sich nicht mit der Verwaltung der Schüsse beschäftigen.

Beste Grüsse

Carsten

https://mastodon.social/@cstrotm https://abbuc.social

AntwortZitat

Meine umständliche Lösung sieht aktuell so aus für 2 Schüsse:

Für die gleichmäßige Bewegung nehme ich den VBI - meine Schüsse laufen von rechts nach links, daher muss ich nur den x-Wert incementieren. Damit der Schuss schneller läuft incrementiere ich 2x!

Diese Routine steht im VBI:

            ;   m1index:
            ;   0 = kein Schuss
            ;   1 = nur Schuss1 läuft
            ;   2 = Schuss1 und 2 laufen
            ;   3 = nur Schuss2 läuft

            #if .byte m1index=#3 .or .byte m1index=#2
            mva xposm2 hposm1
            inc xposm2
            inc xposm2
            #end

            #if .byte m1index=#1 .or .byte m1index=#2
            mva xposm1 hposm0
            inc xposm1
            inc xposm1
            inc m2index
            #end

Die folgende längere Routine wird im Hauptprogramm abgearbeitet:

                            ;Schuss1 

            #if .byte m1index=#0
            #if .byte strig0=#0
            mva xposp1 xposm1
            ldy yposp1
            iny
            iny
            iny
            iny
            iny
            sty yposm1
            lda #170
            sta (miss1),y
            iny
            sta (miss1),y
            inc m1index
            #end
            jmp ex
            #end

            #if .byte m1index=#3
            #if .byte strig0=#0
            mva xposp1 xposm1
            ldy yposp1
            iny
            iny
            iny
            iny
            iny
            sty yposm1
            lda #170
            sta (miss1),y
            iny
            sta (miss1),y
            dec m1index
            #end
            jmp ex
            #end
                            ;Schuss2

            #if .byte m1index=#1 .and .byte m2index>#40
            #if .byte strig0=#0
            mva xposp1 xposm2
            lda #85
            ldy yposp1
            iny
            iny
            iny
            iny
            iny
            sty yposm2
            sta (miss1),y
            iny
            sta (miss1),y
            inc  m1index
            #end
            #end
ex          
            ;   m1index:
            ;   0 = kein Schuss
            ;   1 = nur Schuss1 läuft
            ;   2 = Schuss1 und 2 laufen
            ;   3 = nur Schuss2 läuft

            #if .byte xposm1>#240
            lda #0 
            sta xposm1
            sta hposm0
            ldy yposm1
            mva #0 (miss1),y
            iny
            mva #0 (miss1),y
            inc m1index
            #if .byte m1index=#2
            lda #0 
            sta m1index
            #end
            #end

            #if .byte xposm2>#240 
            lda #0 
            sta xposm2
            sta hposm1
            dec m1index
            ldy yposm2
            mva #0 (miss2),y
            iny
            mva #0 (miss2),y
            #if .byte m1index=#2
            lda #0 
            sta m1index
            sta m2index
            #end
            #end

m1index und m2index beschreiben den Zustand von Schuss1 und Schuss2 - also läuft der jeweilige Schuss gerade. Wenn die x-Position über 240 ist, dann ist der Bildrand erreicht und der jeweilige Schuss wird auf den entsprechenden Index gesetzt. Das Gleiche (dann mit einer Aktion) passiert auch. bei einer Kollision, die ich woanders abfrage.

Insgesamt finde ich das zu umständlich programmiert, mir ist aber nichts besseres im Moment eingefallen. Meine Routine bei Battle of Eris war noch koplizierter...

AntwortZitat

Hi!

Ich möchte hier auch meine Variante vorstellen, wie ich in meinem neuem Spiel die Missiles nutze. Wobei ich wahrscheinlich es noch einmal ändern muss, weil es zuviele mögliche Schüsse sind 🙂

Im Prinzip ist es bei mir 3-teilig.

1) Auslöseroutine 2) Bewegungsroutine 3) Kollisionsroutine

Für die Missiles lege ich mir 4 Variablen an, wobei theoretisch 3 reichen würden: 1) X-Position des Missile 2) Y-Position des Missile 3) Flugrichtung des Missile 4) Status des Missile

Der PM-Speicherstart für die Missiles wird in der Variable "Missiles" hinterlegt.

PMMemBase       EQU $2000               ; $2000 bis $27FF 
Missiles        EQU PMMemBase+$300      
Player0         EQU PMMemBase+$400
Player1         EQU PMMemBase+$500
Player2         EQU PMMemBase+$600
Player3         EQU PMMemBase+$700
MissilesX       .DS 4
MissilesY       .DS 4
MissilesRi      .DS 4
MissilesStat        .DS 4

Die Auslöseroutine:

Diese prüft in einer Schleife, welcher Missile ungenutzt ist (MissilesStat). Der erste ungenutzte Missiles wird im X-Register hinterlegt.

        LDX #3              ; freien Schuss suchen
@       LDA MissilesStat,X      
        BEQ MissileSetzen       ; freier Missile gefunden
        DEX
        BPL @-
        JMP MissileNichtfrei        ; es konnte kein freier Missile gefunden werden

Dadurch ist es egal, welcher der Missiles frei geworden ist, er wird gefunden 😉

Die Routine setzt nun das Missile und die entsprechenden Variablen.

MissileSetzen   LDA #1              ; Missile als aktiv markieren
        STA MissilesStat,X

        LDA PlayerX         ; Missile X setzen
        STA MissilesX,X
        STA HPOSM0,X

        LDA PlayerY         ; Missile Y setzen
        STA MissilesY,X
        TAY
        LDA Missiles,Y          ; Missiles im Speicher lesen
        ORA ShootPixel,X        ; Bits holen
        STA Missiles,Y          ; und zurück speichern

        und Richtung...
        STA MissilesRi,X

        ...
        ...
ShootPixel  DTA %00000011
        DTA %00001100
        DTA %00110000
        DTA %11000000

Da mein Spieler oft auf der selben Höhe seine Schüsse abgibt, ist es wichtig den Missile per ORA hinzuzufügen.

Wenn ein Missile gesetzt wurde, wird es automatisch in der Bewegungsroutine bis zum Bildschirmrand in der angegebenen Richtung bewegt. Am Rand angekommen, wird das Missile gelöscht und der Status auf Inaktiv gesetzt:

ShootOff    LDA #0
        STA MissilesStat,X      ; Status auf 0 = Inaktiv
        LDA MissilesY,X         ; Y-Position holen
        TAY
        LDA Missiles,Y          ; Missile aus Speicher laden
        AND ShootMask,X         ; per Maske löschen
        STA Missiles,Y          ; zurück sichern

        ...
        ...

ShootMask   DTA %11111100
        DTA %11110011
        DTA %11001111
        DTA %00111111       

Wie man ein Missile bewegt und die Kollision prüft, sollte bekannt sein. Beim Bewegen gehe ich übrigens wieder eine Schleife von 3-0 durch und prüfen über den Status, welcher Missile bewegt werden muss. Bei der Kollision müssen ebenfalls nur aktive Missiles geprüft werden.

Möchte man den Missile nach 20 Schritten wieder löschen, kann man leicht in einer weiteren Variable die Anzahl der Schritte sich merken und dann den Missile löschen.

Ich hoffe ich konnte so in etwa aufzeigen, wie ich es mache 🙂

Grüße Janko

Meine Projekte findest Du hier...

AntwortZitat